package com.catazy.mvvmlib.util

import android.util.Log
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject

/**
 * 作者: Tao
 * 日期: 2023/10/30
 * 时间: 14:44
 * 描述: 日志工具类
 */
object LogUtil {

    private const val V = 0X1
    private const val D = 0X2
    private const val I = 0X3
    private const val W = 0X4
    private const val E = 0X5
    private const val A = 0X6
    private const val JSON = 0X7

    private const val DEFAULT_MESSAGE = "execute"
    private const val JSON_INDENT = 4;

    private val LINE_SEPARATOR = System.getProperty("LINE_SEPARATOR ")
    private var isDebug = false

    /**
     * 初始化
     */
    fun init(isDebug: Boolean) {
        LogUtil.isDebug = isDebug;
    }

    fun v() {
        printLog(V, "", DEFAULT_MESSAGE)
    }

    fun v(msg: Any) {
        printLog(V, "", msg)
    }

    fun v(tag: String, msg: Any) {
        printLog(V, tag, msg)
    }

    fun d() {
        printLog(D, "", DEFAULT_MESSAGE)
    }

    fun d(msg: Any) {
        printLog(D, "", msg)
    }

    fun d(tag: String, msg: Any) {
        printLog(D, tag, msg)
    }

    fun i() {
        printLog(I, "", DEFAULT_MESSAGE)
    }

    fun i(msg: Any) {
        printLog(I, "", msg)
    }

    fun i(tag: String, msg: Any) {
        printLog(I, tag, msg)
    }

    fun w() {
        printLog(W, "", DEFAULT_MESSAGE)
    }

    fun w(msg: Any) {
        printLog(W, "", msg)
    }

    fun w(tag: String, msg: Any) {
        printLog(W, tag, msg)
    }

    fun e() {
        printLog(E, "", DEFAULT_MESSAGE)
    }

    fun e(msg: Any) {
        printLog(E, "", msg)
    }

    fun e(tag: String, msg: Any) {
        printLog(E, tag, msg)
    }

    fun a() {
        printLog(A, "", DEFAULT_MESSAGE)
    }

    fun a(msg: Any) {
        printLog(A, "", msg)
    }

    fun a(tag: String, msg: Any) {
        printLog(A, tag, msg)
    }

    fun json() {
        printLog(JSON, "", DEFAULT_MESSAGE)
    }

    fun json(msg: Any) {
        printLog(JSON, "", msg)
    }

    fun json(tag: String, msg: Any) {
        printLog(JSON, tag, msg)
    }

    private fun printLog(type: Int, tagStr: String, objectMsg: Any) {
        if (!isDebug) {
            return
        }
        val stackTrace = Thread.currentThread().stackTrace
        val index = 4;
        val className = stackTrace[index].fileName
        var methodName = stackTrace[index].methodName
        val lineNumber = stackTrace[index].lineNumber
        val tag = tagStr.ifBlank {
            className
        }
        methodName = methodName.substring(0, 1).uppercase() + methodName.substring(1)
        val stringBuilder = StringBuilder()
        stringBuilder.append("[(")
            .append(className)
            .append(":")
            .append(lineNumber)
            .append(")#")
            .append(methodName)
            .append("]")
        val msg: String = objectMsg.toString() ?: "Log with null object"
        if (msg.isNotBlank() && type != JSON) {
            stringBuilder.append(msg)
        }

        val logStr = stringBuilder.toString()
        when (type) {
            V -> {
                Log.v(tag, logStr)
            }
            D -> {
                Log.d(tag, logStr)
            }
            I -> {
                Log.i(tag, logStr)
            }
            W -> {
                Log.w(tag, logStr)
            }
            E -> {
                Log.e(tag, logStr)
            }
            A -> {
                Log.wtf(tag, logStr)
            }
            JSON -> {
                if (msg.isEmpty()) {
                    Log.d(tag, "Empty or null json content")
                    return
                }

                var message: String = ""
                try {
                    if (msg.startsWith("{")) {
                        val jsonObject = JSONObject(msg)
                        message = jsonObject.toString(JSON_INDENT)
                    } else if (msg.startsWith("[")) {
                        val jsonArray = JSONArray(msg)
                        message = jsonArray.toString(JSON_INDENT)
                    }
                } catch (e: JSONException) {
                    e(tag, e.cause?.message + "\n" + msg)
                    return
                }

                printLine(tag, true)
                message = logStr + LINE_SEPARATOR + message
                val lines = message.split(LINE_SEPARATOR as String)
                val jsonContent = StringBuilder()
                for (line: String in lines) {
                    jsonContent.append("║ ")
                        .append(line)
                        .append(LINE_SEPARATOR)
                }

                val json = jsonContent.toString()
                if (json.length > 3200) {
                    Log.w(tag, "jsonContent.length = " + json.length)
                    val chunkCount = json.length / 3200
                    for (i in 0..chunkCount) {
                        val max = 3200 * (i + 1)
                        if (max >= json.length) {
                            Log.w(tag, jsonContent.toString().substring(3200 * i))
                        } else {
                            Log.w(tag, jsonContent.toString().substring(3200 * i, max))
                        }
                    }
                } else {
                    Log.w(tag, jsonContent.toString());
                }
                printLine(tag, false)
            }
        }
    }

    private fun printLine(tag: String, isTop: Boolean) {
        if (isTop) {
            Log.w(
                tag,
                "╔═══════════════════════════════════════════════════════════════════════════════════════"
            );
        } else {
            Log.w(
                tag,
                "╚═══════════════════════════════════════════════════════════════════════════════════════"
            );
        }
    }
}